translator.plugin("translatePage", {

  /**
   * I store a reference to all the text nodes 
   * that will be translated.
   *
   * access private
   * var array
   */
  textNodes : [],

  /**
   * A list of parent nodes I will ignore. 
   * if a given textnode resides within one 
   * of these it wont get translated.
   *
   * @access private
   * @var array
   */
  badNodes : ["SCRIPT", "LINK", "STYLE", "CODE", "HTML:SCRIPT"],

  /**
   * Generates a language sample from the selected 
   * textNodes, this is used to determine the 
   * language of the given page.
   * 
   * @access private
   * @return string
   */
  getSample : function () {
      var sample = "", i = 0;
      while(sample.length < 140) {
        sample += this.textNodes[i].nodeValue;
        i++;        
      } 
      return sample.substring(0, 140);
  },

  /**
   * Determines wheather a node should be translated or not.
   * This is used by the TreeWalker in "this.method".
   *
   * @access private
   * @param DOM_ELMENT (TEXT_NODE)
   * @return bool
   */
  nodeFilter : function (node) {
    if (0 > this.badNodes.indexOf(node.parentNode.nodeName.toUpperCase())) {
      if (false === node.isElementContentWhitespace) {
        if (isNaN(node.nodeValue)) {
          if (1 < node.nodeValue.replace(/^\s+|\s+$/g, "").length) {
            return true;
          }
        }
      }
    }
    return false;
  },

  /**
   * Attempts to translate all the text nodes in "this.textNodes".
   * when they have all been translated fire the provided callback.
   *
   * @access private
   * @param string srcLang 
   * @return void
   */
  translate : function (srcLang, destLang, options) {
    var self = this, done = 0, failed = 0, total = this.textNodes.length;
    var iterator = new translator.iterator(1000, 100);

/*    var frag = options.dom.createDocumentFragment();*/
    var span = options.dom.createElement('span');
/*    frag.appendChild(span);*/

//    this.textNodes.forEach(function (node, id) {*/
      var counter = 0;
      iterator.add(this.textNodes, function () {
        counter++;
        var id = (counter);
        var node = this; 

      translator.translate({
        text : node.nodeValue,
        srcLang : srcLang,
        destLang : destLang,
        success : function (data) {
          done = done + node.nodeValue.length;
          span.innerHTML = data;
          node.nodeValue = span.innerHTML;

          if (done === self.charCount && ("success" in options)) {
            options.success();
            this.textNodes = [];
          }

          if (typeof(options.progress) === 'function') { 
            options.progress(span, done, self.charCount);
          }
        },
        fail : function (error) {
          failed++;
          Application.console.log(error); 
          Application.console.log('Translator: failed to translate node #' + id);
          Application.console.log(node.nodeValue);
        }
      });
    });
  },

  /**
   *
   *
   */
  method : function (options) {
    var self = this;

    var walker = options.dom.createTreeWalker(options.dom, NodeFilter.SHOW_TEXT, { 
      acceptNode : function (node) {
        return self.nodeFilter(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
      }
    }, false);

    this.charCount = 0;

    while(walker.nextNode()) {
      this.charCount = this.charCount + walker.currentNode.nodeValue.length;
      this.textNodes.push(walker.currentNode);
    }

    /*this.textNodes = this.textNodes.sort(function (a, b) {
      return a.nodeValue.length > b.nodeValue.length ? -1 : a.nodeValue.length < b.nodeValue.length ? 1 : 0;
    });*/

    this.translate(options.srcLang, options.destLang, options);
  }
});

